home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / util / misc / Fudgit233.lha / Source / src / vgetargp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-14  |  6.5 KB  |  295 lines

  1. #include <ctype.h>
  2. #include <stdio.h>
  3.  
  4. #include "fudgit.h"
  5. #include "macro.h"
  6. #include "symbol.h"
  7. #include "code.h"
  8. #include "math.tab.h"
  9. #include "head.h"
  10.  
  11. #define SQUOTE '\''
  12. #define DQUOTE '"'
  13. #define BACKSLASH
  14.  
  15. extern int Ft_almost(char *, char *);
  16.  
  17. #define COPY(pOinter)    *cp++ = p[argno][j++] = *pOinter++;\
  18.                         if (j >= TOKENSIZE) {\
  19.                         fprintf(stderr, "Argument %d too long.\n", argno);\
  20.                         return(ERRR);\
  21.                         }
  22.  
  23. #define CHECKMODE        if (leavequotes == ERRR) {\
  24.                             leavequotes = (Ft_almost(p[0], "pm!ode") ||\
  25.                             Ft_almost(p[0], "cm!ode") ||\
  26.                             Ft_almost(p[0], "le!t") ||\
  27.                             Ft_maclook(p[0], ANALIAS) );\
  28.                             if (leavequotes) {\
  29.                                 COPY(b);\
  30.                                 break;\
  31.                             }\
  32.                         }\
  33.  
  34. /* given a buffered line b, a string vector p, return the number of
  35.  * arguments found and copied. expand local variables.
  36.  * Returns: no of arg
  37.  * NL for newline
  38.  * ERRR for serious errors
  39.  * VERRR for variable errors (for history purposes)
  40.  */
  41.  
  42. extern char Ft_Vformat[];
  43. extern char Ft_Comchar;
  44. extern char Ft_Home[];
  45. extern int Ft_iolevel(void);
  46. extern char *getenv(const char *);
  47. static char buffer[LINESIZE];
  48.  
  49. int Ft_vgetargp(char *b, char **p, int type, char **add)
  50. {
  51.     static char qtstype[] = "\"'";
  52.     int j = 0;
  53.     int argno = 0;
  54.     int indquotes = 0;
  55.     int insquotes = 0;
  56.     int inpar = 0;
  57.     int expansion = (type & EXPANSION);
  58.     int quotes = (type & QUOTES);
  59.     int parenth = (type & PARENTH);
  60.     int leavequotes = (quotes == 0? YES: ERRR);
  61.     char *cp = buffer;
  62.     char *np;
  63.  
  64.     if (add)
  65.         *add = cp;
  66.  
  67.     /* remove leading blanks  */
  68.     while (*b != '\0' && (*b == ' ' || *b == '\t' || *b == '\n'))
  69.         b++;
  70.     if (*b == '\0') return(NL);
  71.  
  72.     /* go along the string  */
  73.     while (*b != '\0' && argno < MAXTOKEN) {
  74.         switch (*b) {
  75. #ifdef BACKSLASH
  76.         case '\\':    /* only recognize \$ in non fmodes  */
  77.             if (leavequotes == ERRR) {
  78.                 leavequotes = (    Ft_almost(p[0], "pm!ode") ||
  79.                                 Ft_almost(p[0], "cm!ode") ||
  80.                                 Ft_almost(p[0], "le!t")   );
  81.             }
  82.             if (expansion && (!leavequotes || b[1] == '$')) {
  83.                 b++;
  84.             }
  85.             COPY(b);
  86.             break;
  87. #endif
  88.         case SQUOTE:  /* take following as one string, + turn off exp */
  89.             if (leavequotes == 1 || indquotes || inpar) {
  90.                 COPY(b);
  91.                 break;
  92.             }
  93.             CHECKMODE;
  94.             b++;
  95.             insquotes = !insquotes;
  96.             break;
  97.         case DQUOTE:  /* take the following as one string */
  98.             if (leavequotes == 1 || insquotes || inpar) {
  99.                 COPY(b);
  100.                 break;
  101.             }
  102.             CHECKMODE;
  103.             b++;
  104.             indquotes = !indquotes;
  105.             break;
  106.         case '$':  /* try to expand a numeric variable  */
  107.             if (!insquotes && expansion &&
  108.             (*(b+1) == '{' || *(b+1) == '[' ||
  109.                 *(b+1) == '_' || isalpha((int)*(b+1)))) {
  110.                 Symbol *sym;
  111.                 char name[TOKENSIZE];
  112.                 char format[TOKENSIZE];
  113.                 char *lp;
  114.                 int brace = 0;
  115.                 int bracket = 0;
  116.  
  117.                 b++;
  118.                 if (*b == '{') {
  119.                     b++;
  120.                     brace = 1;
  121.                 }
  122.                 if (*b == '[') {
  123.                     b++;
  124.                     bracket = 1;
  125.                     np = format;
  126.                     while (*b && *b != ']') {
  127.                         *np++ = *b++;
  128.                     }
  129.                     *np = '\0';
  130.                     if (*b++ != ']') {
  131.                         fprintf(stderr, "Unmatched bracket: %s.\n", format);
  132.                         return(VERRR);
  133.                     }
  134.                 }        
  135.                 np = name;
  136.                 /* name is alphanumeric */
  137.                 while (*b == '_' || isalnum((int)*b)) { 
  138.                     *np++ = *b++;
  139.                 }
  140.                 *np = '\0';
  141.                 if (brace) {
  142.                     if (*b++ != '}') {
  143.                         fprintf(stderr, "Unmatched brace: %s.\n", name);
  144.                         return(VERRR);
  145.                     }
  146.                 }
  147.                 /* find the variable */
  148.                 if ((sym = Ft_lookup(name)) == 0) {
  149.                     fprintf(stderr,
  150.                     "Expansion error: %s: No such constant or variable.\n",
  151.                     name);
  152.                     return(VERRR);
  153.                 }
  154.                 /* The following crucially depends on the order in parse.y */
  155.                 if (sym->type >= VAR && sym->type <= BLTINCONST) {
  156.                     if (bracket)
  157.                         lp = format;
  158.                     else
  159.                         lp = Ft_Vformat;
  160.                     sprintf(name, lp, sym->u.val);
  161.                     lp = name;
  162.                 }
  163.                 else if (sym->type >= STRVAR && sym->type <= BLTINSTRCONST) {
  164.                     if (bracket) {
  165.                         sprintf(name, format, sym->u.str);
  166.                         lp = name;
  167.                     }
  168.                     else
  169.                         lp = sym->u.str;
  170.                 }
  171.                 else if (sym->type == UNDEFSTRVAR || sym->type == UNDEFVAR) {
  172.                     fprintf(stderr,
  173.                     "Expansion error: %s: Undefined variable.\n", name);
  174.                     return(VERRR);
  175.                 }
  176.                 else {
  177.                     fprintf(stderr,
  178.                     "Expansion error: %s: Not a printable variable.\n", name);
  179.                     return(VERRR);
  180.                 }
  181.                 while(*lp) {   /* replace by value */
  182.                     COPY(lp);
  183.                 }
  184.             }
  185.             else { /* copy $ as is */
  186.                 COPY(b);
  187.             }
  188.             break;
  189.         case '(':
  190.             if (!parenth || (leavequotes == 1 && quotes == 1)
  191.                 || indquotes || insquotes) {
  192.                 COPY(b);
  193.                 break;
  194.             }
  195.             CHECKMODE;
  196.             inpar++;
  197.             if (inpar == 1 && j != 0) { /* start new argument on first '(' */
  198.                 p[argno][j] = '\0';
  199.                 argno++;
  200.                 j = 0;
  201.             }
  202.             COPY(b);
  203.             break;
  204.         case ')':
  205.             if (!parenth || (leavequotes == 1 && quotes == 1)
  206.                 || indquotes || insquotes) {
  207.                 COPY(b);
  208.                 break;
  209.             }
  210.             CHECKMODE;
  211.             inpar--;
  212.             COPY(b);
  213.             if (inpar == 0 && !isspace(*b)) { /* end argument on last ')' */
  214.                 p[argno][j] = '\0';
  215.                 argno++;
  216.                 j = 0;
  217.             }
  218.             break;
  219.         case ' ':   /* a space  */
  220.         case '\t':
  221.             if (indquotes || inpar || insquotes) {
  222.                 p[argno][j] = ' ';
  223.                 j++;
  224.             }
  225.             else {
  226.                 p[argno][j] = '\0';
  227.                 argno++;
  228.                 j = 0;
  229.             }
  230.             *cp = ' '; cp++;
  231.             /* remove interargument blanks  */
  232.             while (*b == ' ' || *b == '\t')
  233.                 b++;
  234.             if (*b == '\n') {
  235.                 if (inpar) {
  236.                     fprintf(stderr, "Unmatched %c.\n",
  237.                     inpar>0? '(' : ')');
  238.                     return(VERRR);
  239.                 }
  240.                 if (indquotes || insquotes) {
  241.                     fprintf(stderr, "Unmatched %c.\n", qtstype[insquotes]);
  242.                     return(VERRR);
  243.                 }
  244.                 b++;
  245.                 if (*b != '\0') {
  246.                     fputs("Command contains more than one line.\n", stderr);
  247.                     return(ERRR);
  248.                 }
  249.                 *cp = '\n'; cp++; *cp = '\0';
  250.                 return(argno);
  251.             }
  252.             break;
  253.         case '\n':
  254.             if (inpar) {
  255.                 fprintf(stderr, "Unmatched %c.\n",
  256.                     inpar>0? '(' : ')');
  257.                 return(VERRR);
  258.             }
  259.             if (insquotes || indquotes) {
  260.                 fprintf(stderr, "Unmatched %c.\n", qtstype[insquotes]);
  261.                 return(VERRR);
  262.             }
  263.             *cp = '\n'; cp++;
  264.             *cp = p[argno][j] = '\0';
  265.             argno++; b++;
  266.             if (*b != '\0') {
  267.                 fputs("Command contains more than one line.\n", stderr);
  268.                 return(ERRR);
  269.             }
  270.             return(argno);
  271.         case '~':
  272.             b++;
  273.             np = Ft_Home;
  274.             while (*np) {   /* replace by variable */
  275.                 COPY(np);
  276.             }    
  277.             break;
  278.         default:
  279.             /* ignore comment except when interactive */
  280.             if (*b == Ft_Comchar && !indquotes && !insquotes &&
  281.              !inpar && (Ft_iolevel() || !expansion)) {
  282.                 *cp = '\n'; cp++;
  283.                 *cp = p[argno][j] = '\0';
  284.                 if (j != 0) argno++;
  285.                 return(argno);
  286.             } /* otherwise go through */
  287.             COPY(b);
  288.             break;
  289.         }
  290.     }
  291.     fputs("Tokenizer: Line too long or not terminated.\n", stderr);
  292.     return(ERRR);
  293. }
  294.  
  295.